#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define NUM_PROCESSES 5

typedef struct PCB {
    char name[3];
    struct PCB *next;
    int run_time;
    int priority;
    char status;
} PCB;

void print_queue(PCB *head) {
    PCB *current = head;
    printf("Queue: ");
    while (current != NULL) {
        printf("%s ", current->name);
        current = current->next;
    }
    printf("\n");
}

void print_processes(PCB processes[]) {
    printf("Processes:\n");
    for (int i = 0; i < NUM_PROCESSES; i++) {
        printf("%s %d %d %c\n", processes[i].name, processes[i].run_time, processes[i].priority, processes[i].status);
    }
}

PCB *get_highest_priority_process(PCB processes[]) {
    PCB *highest_priority_process = NULL;
    for (int i = 0; i < NUM_PROCESSES; i++) {
        if (processes[i].status == 'R') {
            if (highest_priority_process == NULL || processes[i].priority > highest_priority_process->priority) {
                highest_priority_process = &processes[i];
            }
        }
    }
    return highest_priority_process;
}

void insert_into_queue(PCB **head, PCB *process) {
    if (*head == NULL || process->priority > (*head)->priority) {
        process->next = *head;
        *head = process;
    } else {
        PCB *current = *head;
        while (current->next != NULL && current->next->priority > process->priority) {
            current = current->next;
        }
        process->next = current->next;
        current->next = process;
    }
}

void priority_scheduling(PCB processes[]) {
    PCB *queue_head = NULL;

    for (int i = 0; i < NUM_PROCESSES; i++) {
        insert_into_queue(&queue_head, &processes[i]);
    }

    while (queue_head != NULL) {
        print_queue(queue_head);
        print_processes(processes);

        PCB *highest_priority_process = queue_head;
        queue_head = queue_head->next;

        printf("Running process: %s\n", highest_priority_process->name);

        highest_priority_process->run_time--;
        highest_priority_process->priority--;

        if (highest_priority_process->run_time == 0) {
            highest_priority_process->status = 'E';
            highest_priority_process->next = NULL;
        } else {
            insert_into_queue(&queue_head, highest_priority_process);
        }
    }

    print_queue(queue_head);
    print_processes(processes);
}

int main() {
    PCB processes[NUM_PROCESSES] = {
            {"P1", NULL, 2, 3, 'R'},
            {"P2", NULL, 3, 1, 'R'},
            {"P3", NULL, 1, 4, 'R'},
            {"P4", NULL, 2, 5, 'R'},
            {"P5", NULL, 4, 2, 'R'}
    };

    priority_scheduling(processes);

    return 0;
}
